# -*- coding: utf-8 -*-
"""
MQTT远程升级服务
"""
import json
import logging
from typing import List, Dict, Tuple
from app.model import MQTTConfig, DeviceModel, UpgradeRecord
from mqtt_utils.mqtt_client import MQTTClient


class MQTTUpgradeService:
    """MQTT远程升级服务类"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def send_upgrade_command(self, device_names: List[str], upgrade_message: Dict, 
                           config_id: int = None) -> Dict:
        """
        发送远程升级命令
        
        Args:
            device_names: 设备名称列表
            upgrade_message: 升级消息内容
            config_id: MQTT配置ID，如果为None则使用默认配置
        
        Returns:
            包含升级结果的字典
        """
        try:
            # 获取MQTT配置
            mqtt_config = self._get_mqtt_config(config_id)
            if not mqtt_config:
                return {
                    'success': False,
                    'error': '未找到有效的MQTT配置'
                }
            
            # 创建升级记录
            record_data = {
                'config_id': mqtt_config.id,
                'device_names': device_names,
                'upgrade_message': upgrade_message,
                'status': 'PENDING'
            }
            upgrade_record = UpgradeRecord.create_record(record_data)
            
            # 执行升级
            result = self._execute_upgrade(
                mqtt_config, device_names, upgrade_message, upgrade_record
            )
            
            return {
                'success': True,
                'upgrade_record_id': upgrade_record.id,
                'result': result
            }
            
        except Exception as e:
            self.logger.error(f"发送升级命令失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def _get_mqtt_config(self, config_id: int = None) -> MQTTConfig:
        """获取MQTT配置"""
        if config_id:
            return MQTTConfig.get_config_by_id(config_id)
        else:
            return MQTTConfig.get_default_config()
    
    def _execute_upgrade(self, mqtt_config: MQTTConfig, device_names: List[str], 
                        upgrade_message: Dict, upgrade_record: UpgradeRecord) -> Dict:
        """执行升级操作"""
        failed_devices = []
        success_devices = []
        
        try:
            # 创建MQTT客户端
            mc = MQTTClient(
                mqtt_config.broker,
                mqtt_config.port,
                mqtt_config.client_id,
                mqtt_config.username,
                mqtt_config.password
            )
            
            # 遍历设备列表
            for device_name in device_names:
                try:
                    device_result = self._upgrade_single_device(
                        mc, device_name, upgrade_message
                    )
                    
                    if device_result['success']:
                        success_devices.append(device_result['data'])
                    else:
                        failed_devices.append({
                            'device_name': device_name,
                            'error': device_result['error']
                        })
                        
                except Exception as e:
                    failed_devices.append({
                        'device_name': device_name,
                        'error': str(e)
                    })
                    self.logger.error(f"设备 {device_name} 升级失败: {str(e)}")
            
            # 更新升级记录状态
            status, error_msg = self._determine_upgrade_status(
                success_devices, failed_devices
            )
            upgrade_record.update_status(status, error_msg)
            
            return {
                'mqtt_config': mqtt_config.config_name,
                'success_count': len(success_devices),
                'failed_count': len(failed_devices),
                'success_devices': success_devices,
                'failed_devices': failed_devices,
                'status': status
            }
            
        except Exception as e:
            # 更新升级记录为失败状态
            upgrade_record.update_status('FAILED', f"MQTT连接或发送失败: {str(e)}")
            raise e
    
    def _upgrade_single_device(self, mc: MQTTClient, device_name: str, 
                              upgrade_message: Dict) -> Dict:
        """升级单个设备"""
        try:
            # 从device_models表中查找设备
            device = DeviceModel.query.filter_by(model_name=device_name).first()
            if not device:
                return {
                    'success': False,
                    'error': '设备不存在'
                }
            
            # 发送MQTT消息
            topic = f"device/{device.vuid}/ota_cmd"
            mc.publish_message(topic, upgrade_message)
            
            return {
                'success': True,
                'data': {
                    'device_name': device_name,
                    'vuid': device.vuid,
                    'topic': topic
                }
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': str(e)
            }
    
    def _determine_upgrade_status(self, success_devices: List, 
                                 failed_devices: List) -> Tuple[str, str]:
        """确定升级状态"""
        if failed_devices:
            if success_devices:
                status = 'PARTIAL_SUCCESS'
                error_msg = f"部分设备升级失败: {json.dumps(failed_devices, ensure_ascii=False)}"
            else:
                status = 'FAILED'
                error_msg = f"所有设备升级失败: {json.dumps(failed_devices, ensure_ascii=False)}"
        else:
            status = 'SUCCESS'
            error_msg = None
        
        return status, error_msg
    
    def get_device_vuids(self, device_names: List[str]) -> Dict[str, str]:
        """
        获取设备名称对应的VUID映射
        
        Returns:
            设备名称到VUID的映射字典
        """
        device_vuid_map = {}
        
        for device_name in device_names:
            device = DeviceModel.query.filter_by(model_name=device_name).first()
            if device:
                device_vuid_map[device_name] = device.vuid
        
        return device_vuid_map
    
    def validate_upgrade_message(self, upgrade_message: Dict) -> Tuple[bool, str]:
        """
        验证升级消息格式
        
        Returns:
            (是否有效, 错误信息)
        """
        required_fields = ['fileName', 'version', 'downloadURL', 'fileMd5']
        
        for field in required_fields:
            if field not in upgrade_message:
                return False, f"缺少必填字段: {field}"
        
        # 可以添加更多的验证逻辑
        # 例如：URL格式验证、版本号格式验证等
        
        return True, "" 